package thuai.ccf2013.query;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import thu.ccf2013.wiki.Infobox;
import thuai.ccf2013.driver.Driver;
import thuai.ccf2013.util.MyStrUtil;

public class FeatureExtractor {

	public static double[] evaluate(Entity entity, Infobox box) {
		List<Double> feature = new ArrayList<Double>();

		// dim 0: edit distance between entity name and box name
		// feature.add(Math.exp(-MyStrUtil.LevenshteinDistance(entity.getName(),
		// box.getName())));
		feature.add((double) MyStrUtil.LevenshteinDistance(entity.getName(),
				box.getName()));

		// dim 1: minimum edit distance between entity name and box facts
		int min = MyStrUtil.LevenshteinDistance(entity.getName(),
				box.getAnchorText());
		for (String content : box.getFacts().values()) {
			int dis = MyStrUtil.LevenshteinDistance(entity.getName(), content);
			if (dis < min)
				min = dis;
		}

		// feature.add(Math.exp(-min));
		feature.add((double) min);
		
		// dim 2: the ratio of length of infobox name and entity name
		feature.add((double)box.getName().length() / entity.getName().length());
		
		// dim 3: the ratio of length of infobox anchor text and entity name
		feature.add((double)box.getAnchorText().length() / entity.getName().length());
		
		// dim 4: whether entity name is part of box name
		if (box.getName().contains(entity.getName())) {
			feature.add(1.0);
		} else {
			feature.add(0.0);
		}
		
		// dim 5: whether entity name is part of box anchor Text
		if (box.getAnchorText().contains(entity.getName())) {
			feature.add(1.0);
		} else {
			feature.add(0.0);
		}
		
		// features below are related to synonyms
		
		// dim 5, 6: count of common chars of synonym in name and anchor text
		// dim 7: count of common chars in facts
		int comNameCount = 0, comAnchorCount = 0, comFactCount = 0;
		if (Driver.extendNameDict.containsKey(entity.getName())) {
			List<String> list = Driver.extendNameDict.get(entity.getName());
			for (int i = 0; i < list.size(); i++) {
				comNameCount += MyStrUtil.comSubstring(list.get(i), box.getName()).length();
				comAnchorCount += MyStrUtil.comSubstring(list.get(i), box.getAnchorText()).length();
				for (String content : box.getFacts().values()) {
					comFactCount += MyStrUtil.comSubstring(list.get(i), content).length();
				}
			}
		}
		feature.add((double) comNameCount);
		feature.add((double) comAnchorCount);
		feature.add((double) comFactCount);
		
		// dim 9:  count of keyword in page content
		// dim 10: count of n-grams of title in page content
		// dim 11: count of n-grams of summary in page content
		// dim 12: count of synonym in page content
		// dim 13: appearence of other keywords in the same weibo in page count
		
		int nameInContentCount = 0;
		int tittInContentCount = 0;
		int summInContentCount = 0;
		int synInContentCount = 0;
		
		
		List<String> page = box.getPage();
		Iterator<String> pIter = page.iterator();
		while (pIter.hasNext()) {
			String line = pIter.next();
			int begin = 0;
			while ((begin = line.indexOf(entity.getName(), begin)) >= 0) {
				begin++;
				nameInContentCount++;
			}
		}
		feature.add((double) nameInContentCount);
		
		String cleanName = MyStrUtil.getRidOfSymbol(entity.getName());
		if (Driver.tittNameDict.containsKey(cleanName)) {
			pIter = page.iterator();
			while (pIter.hasNext()) {
				String line = pIter.next();				
				List<String> list = Driver.tittNameDict.get(cleanName);
				Iterator<String> sIter = list.iterator();
				while (sIter.hasNext()) {
					String syn = sIter.next();
					int begin = 0;
					while ((begin = line.indexOf(syn, begin)) >= 0) {
						begin++;
						tittInContentCount++;
					}
				}
			}
		}
		feature.add((double) tittInContentCount);
		
		if (Driver.summNameDict.containsKey(cleanName)) {
			pIter = page.iterator();
			while (pIter.hasNext()) {
				String line = pIter.next();				
				List<String> list = Driver.summNameDict.get(cleanName);
				Iterator<String> sIter = list.iterator();
				while (sIter.hasNext()) {
					String syn = sIter.next();
					int begin = 0;
					while ((begin = line.indexOf(syn, begin)) >= 0) {
						begin++;
						summInContentCount++;
					}
				}
			}
		}
		feature.add((double) summInContentCount);
		
		if (Driver.extendNameDict.containsKey(entity.getName())) {
			pIter = page.iterator();
			while (pIter.hasNext()) {
				String line = pIter.next();				
				List<String> list = Driver.extendNameDict.get(cleanName);
				Iterator<String> sIter = list.iterator();
				while (sIter.hasNext()) {
					String syn = sIter.next();
					int begin = 0;
					while ((begin = line.indexOf(syn, begin)) >= 0) {
						begin++;
						synInContentCount++;
					}
				}
			}
		}
		feature.add((double) synInContentCount);
		
		Query q = entity.getParentQuery();
		List<Entity> el = q.getEntityList();
		int coAppearance = 0;
		
		String[] names = new String[el.size()];
		for (int i = 0; i < el.size(); i++) {
			names[i] = el.get(i).getName();
		}
		pIter = page.iterator();
		while (pIter.hasNext()) {
			String line = pIter.next();
			for (int i = 0; i < names.length; i++) {
				if (names[i].equals(entity.getName())) continue;
				int begin = 0;
				while ((begin = line.indexOf(entity.getName(), begin)) >= 0) {
					begin++;
					coAppearance++;
				}
			}
		}
		
		feature.add((double) coAppearance);
		
		// dim 14: result of lucence, appear twice, once, or no appearence
		
		int lucAppearance = 0;
		if (Driver.luceneRank.containsKey(cleanName)) {
			if (Driver.luceneRank.get(cleanName).containsKey(box.getId())) {
				lucAppearance = Driver.luceneRank.get(cleanName).get(box.getId());
			}
		}
		feature.add((double) lucAppearance);
		
		double[] f = new double[feature.size()];
		for (int i = 0; i < f.length; i++) {
			f[i] = feature.get(i);
		}
		return f;
		
	}
	
	public static double[] evaluate(Query query, Infobox box) {
		return null;
	}
	
	public static double[] evaluate(Infobox box1, Infobox box2) {
		return null;
	}
	

}
